﻿using System.Collections;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Internal;


//https://learn.microsoft.com/zh-cn/dotnet/core/extensions/caching

namespace MemoryCacheExample;

/// <summary>
/// 系统缓存
/// </summary>
public abstract class MemoryCacheHelper
{
    private static readonly IMemoryCache Cache = new MemoryCache(new MemoryCacheOptions());


    #region ======== 通用操作 ========

    /// <summary>
    /// 缓存对象是否存在
    /// </summary>
    public static bool Exists(string key)
    {
        if (key == null) throw new ArgumentNullException(nameof(key));
        return Cache.TryGetValue(key, out _);
    }

    // /// <summary>
    // /// 获取所有缓存键
    // /// </summary>
    // public static List<string> AllKeys()
    // {
    //     const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
    //     var entries = Cache.GetType().GetField("_entries", flags)?.GetValue(Cache);
    //     var keys = new List<string>();
    //     if (entries is not IDictionary cacheItems) return keys;
    //     keys.AddRange(from DictionaryEntry cacheItem in cacheItems select cacheItem.Key.ToString());
    //     return keys;
    // }
    
    
    #endregion

    #region ======== 添加缓存 ========

    /// <summary>
    /// 添加缓存
    /// </summary>
    public static bool Set(string key, object value)
    {
        if (key == null) throw new ArgumentNullException(nameof(key));
        if (value == null) throw new ArgumentNullException(nameof(value));
        Cache.Set(key, value);
        return Exists(key);
    }

    /// <summary>
    /// 添加缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <param name="value">缓存Value</param>
    /// <param name="expiresIn">缓存时长</param>
    /// <param name="isSliding">是否滑动过期(有效期内有操作,则以当前时间点延长过期时间)</param>
    /// <returns></returns>
    public static bool Set(string key, object value, TimeSpan expiresIn, bool isSliding = false)
    {
        if (key == null) throw new ArgumentNullException(nameof(key));
        if (value == null) throw new ArgumentNullException(nameof(value));
        Cache.Set(key, value, isSliding
            ? new MemoryCacheEntryOptions().SetSlidingExpiration(expiresIn)
            : new MemoryCacheEntryOptions().SetAbsoluteExpiration(expiresIn));
        return Exists(key);
    }

    /// <summary>
    /// 添加缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <param name="value">缓存Value</param>
    /// <param name="expiresSliding">是否滑动过期(有效期内有操作,则以当前时间点延长过期时间)</param>
    /// <param name="expiresAbsolute">绝对过期时长</param>
    /// <returns></returns>
    public static bool Set(string key, object value, TimeSpan expiresSliding, TimeSpan expiresAbsolute)
    {
        if (key == null) throw new ArgumentNullException(nameof(key));
        if (value == null) throw new ArgumentNullException(nameof(value));
        Cache.Set(key, value, new MemoryCacheEntryOptions()
            .SetSlidingExpiration(expiresSliding)
            .SetAbsoluteExpiration(expiresAbsolute));
        return Exists(key);
    }

    #endregion


    #region ======== 读取缓存 ========

    /// <summary>
    /// 获取缓存
    /// </summary>
    public static object? Get(string key)
    {
        if (key == null) throw new ArgumentNullException(nameof(key));
        return Cache.Get(key);
    }
    
    /// <summary>
    /// 获取缓存
    /// </summary>
    public static T? Get<T>(string key) where T : class
    {
        if (key == null) throw new ArgumentNullException(nameof(key));
        return Cache.Get(key) as T;
    }
    

    /// <summary>
    /// 获取缓存集合
    /// </summary>
    public static IDictionary<string, object> GetAll(IEnumerable<string> keys)
    {
        if (keys == null) throw new ArgumentNullException(nameof(keys));
        var dict = new Dictionary<string, object>();
        keys.ToList().ForEach(item => dict.Add(item, Cache.Get(item)));
        return dict;
    }

    /// <summary>
    /// 获取缓存集合
    /// </summary>
    public static IDictionary<string,T> GetAll<T>(IEnumerable<string> keys) 
    {
        if (keys == null) throw new ArgumentNullException(nameof(keys));
        var dict = new Dictionary<string, T>();
        keys.ToList().ForEach(item => dict.Add(item, Cache.Get<T>(item)));
        return dict;
    }



    #endregion


    #region ======== 移除缓存 ========

    /// <summary>
    /// 删除缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static void Remove(string key)
    {
        if (key == null) throw new ArgumentNullException(nameof(key));
        Cache.Remove(key);
    }

    /// <summary>
    /// 批量删除缓存
    /// </summary>
    public static void Remove(IEnumerable<string> keys)
    {
        if (keys == null) throw new ArgumentNullException(nameof(keys));
        keys.ToList().ForEach(item => Cache.Remove(item));
    }

    // /// <summary>
    // /// 删除所有缓存
    // /// </summary>
    // public static void RemoveAll()
    // {
    //     Remove(AllKeys());
    // }
    //
    //
    // /// <summary>
    // /// 删除匹配到的缓存
    // /// </summary>
    // /// <param name="pattern">正则表达式</param>
    // public static void RemovePattern(string pattern)
    // {
    //     var matchedKeys = Cache.AllKeys().Where(x => Regex.IsMatch(x, pattern)).ToList().AsReadOnly();
    //     foreach (var key in matchedKeys)
    //     {
    //         Cache.Remove(key);
    //     }
    // }

    #endregion
}